package com.egdigital.allzic.ui.activity;

import java.io.IOException;
import java.util.List;

import android.app.AlertDialog;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import com.android.volley.toolbox.Volley;
import com.egdigital.allzic.R;
import com.egdigital.allzic.adswizz.AdsHttpRequest;
import com.egdigital.allzic.adswizz.XMLHandler;
import com.egdigital.allzic.data.json.JsonCacheManager;
import com.egdigital.allzic.data.object.Category;
import com.egdigital.allzic.data.object.Country;
import com.egdigital.allzic.data.object.Department;
import com.egdigital.allzic.data.object.Station;
import com.egdigital.allzic.service.ServiceStreaming;
import com.egdigital.allzic.ui.ScrollingTextView;
import com.egdigital.allzic.utils.ImageManager;
import com.egdigital.allzic.utils.NetworkManager;
import com.egdigital.allzic.utils.PrefManager;
import com.egdigital.allzic.utils.Utils;

public class BaseActivity extends SherlockFragmentActivity implements OnClickListener {

	private static final String		TAG						= BaseActivity.class.getSimpleName();	// log
	// minimum limit of char count for search
	public static final int			CHAR_MIN_BEFORE_SEARCH	= 1;
	// lists of data
	private List<Station>			mListAllZic;
	private List<Category>			mListCategory;
	private List<Country>			mListCountry;
	private List<Department>		mListDepartment;
	//
	private static Station			mCurrentStation;
	// menu
	public boolean					mCategorySelected		= false;								// block the lists during processing and transitions
	public boolean					mExplorerSelected		= false;
	//
	private boolean					mPlayerResultPlay		= false;								// determine if the music should play at player activity boot
	protected static final int		PLAYER_MUST_PLAY_INTENT	= 1006;								// label for the intent
	// streaming service
	protected ServiceStreaming		mServiceRadio;
	protected ServiceConnection		mServiceConnexionRadio;
	// ui
	protected LinearLayout			mPlayerLayout;
	protected ImageButton			mPlayerButtonPlay;
	protected ImageButton			mPlayerButtonFavorite;
	protected TextView				mPlayerTitle;
	public ProgressBar				mPlayerLoading;
	protected ImageView				mPlayerThumb;
	protected ScrollingTextView		mPlayerSubTitle;
	protected RelativeLayout		mLoadingView;
	protected LinearLayout			mReloadView;
	protected TextView				mNoResultView;
	//
	protected DownloadState			mDownloadState			= DownloadState.LOADING;
	//
	final public BroadcastReceiver	mPlayBackReceiver		= new BroadcastReceiver() {

																@Override
																public void onReceive(Context context, Intent intent) {
																	String actionString = intent.getAction();
																	Log.w(TAG, actionString);
																	if (actionString == ServiceStreaming.SERVICE_PLAY) { // play
																		mPlayerButtonPlay.setImageResource(R.drawable.selector_btn_stop_small);
																		mPlayerButtonPlay.setEnabled(true);
																		mPlayerButtonPlay.setVisibility(View.VISIBLE);
																		mPlayerLoading.setVisibility(View.GONE);
																	} else if (actionString == ServiceStreaming.SERVICE_STOP) { // stop
																		AdsHttpRequest.getInstance().cancelGetTask();
																		mPlayerButtonPlay.setImageResource(R.drawable.selector_btn_play_small);
																		mPlayerButtonPlay.setEnabled(true);
																		mPlayerButtonPlay.setVisibility(View.VISIBLE);
																		mPlayerLoading.setVisibility(View.GONE);
																	} else if (actionString == ServiceStreaming.SERVICE_LOADING) { // loading not really used for now
																	} else if (actionString == ServiceStreaming.SERVICE_ERROR) { // error
																		mPlayerButtonPlay.setImageResource(R.drawable.selector_btn_play_small);
																		mPlayerButtonPlay.setEnabled(true);
																		mPlayerButtonPlay.setVisibility(View.VISIBLE);
																		mPlayerLoading.setVisibility(View.GONE);
																	} else if (actionString == ServiceStreaming.SERVICE_KILLED) { // service killed
																		mPlayerButtonPlay.setImageResource(R.drawable.selector_btn_play_small);
																		mPlayerButtonPlay.setEnabled(true);
																		mPlayerButtonPlay.setVisibility(View.VISIBLE);
																		mPlayerLoading.setVisibility(View.GONE);
																	} else if (actionString == ServiceStreaming.SERVICE_METADATA) { // metadata datas not used for now
																		// PrefManager preferenceManager = PrefManager.getInstance(getApplicationContext());
																		// String key = intent.getExtras().getString(ServiceStreaming.SERVICE_METADATA + "_key");
																		// String value = intent.getExtras().getString(ServiceStreaming.SERVICE_METADATA + "_value");
																		// if (key != null) {
																		// if (key.equalsIgnoreCase("metadata")) {
																		// String substr = value.substring(value.indexOf("=") + 1);
																		// preferenceManager.addString_Pref("adswizz_context", substr);
																		// } else if (key.equalsIgnoreCase("durationMilliseconds")) {
																		// preferenceManager.addLong_pref("adswizz_duration", Long.parseLong(value));
																		// }
																		// }
																	}
																}
															};

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.setVolumeControlStream(AudioManager.STREAM_MUSIC); // activate music volume
		mServiceConnexionRadio = new ServiceConnection() { // streaming service

			@Override
			public void onServiceDisconnected(ComponentName name) {
				mServiceRadio = null; // clean up service instance
			}

			@Override
			public void onServiceConnected(ComponentName name, IBinder binder) {
				if (mServiceRadio == null) {
					mServiceRadio = (ServiceStreaming) ((ServiceStreaming.PlayerBinder) binder).getServiceInstance();
				}
				Station station = getmCurrentStation();
				if (station != null) {
					showPlayerBanner();
					updatePlayerBanner();
				}
				mPlayerButtonPlay.setEnabled(true); // ready to interract with UI
				mPlayerButtonPlay.setVisibility(View.VISIBLE);
			}
		};
		mPlayerButtonPlay.setEnabled(true);
		LocalBroadcastManager.getInstance(this).registerReceiver((mPlayBackReceiver), new IntentFilter(ServiceStreaming.SERVICE_PLAY));
		LocalBroadcastManager.getInstance(this).registerReceiver((mPlayBackReceiver), new IntentFilter(ServiceStreaming.SERVICE_STOP));
		LocalBroadcastManager.getInstance(this).registerReceiver((mPlayBackReceiver), new IntentFilter(ServiceStreaming.SERVICE_LOADING));
		LocalBroadcastManager.getInstance(this).registerReceiver((mPlayBackReceiver), new IntentFilter(ServiceStreaming.SERVICE_METADATA));
		LocalBroadcastManager.getInstance(this).registerReceiver((mPlayBackReceiver), new IntentFilter(ServiceStreaming.SERVICE_ERROR));
		LocalBroadcastManager.getInstance(this).registerReceiver((mPlayBackReceiver), new IntentFilter(ServiceStreaming.SERVICE_KILLED));
	}

	@Override
	protected void onResume() {
		super.onResume();
		bindServices();
	}

	@Override
	protected void onPause() {
		unbindServices();
		super.onPause();
	}

	@Override
	protected void onDestroy() {
		if (mPlayBackReceiver != null) {
			LocalBroadcastManager.getInstance(this).unregisterReceiver(mPlayBackReceiver);
		}
		super.onDestroy();
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
		if (requestCode == PLAYER_MUST_PLAY_INTENT) {
			if (resultCode == RESULT_OK) {
				mPlayerResultPlay = intent.getExtras().getBoolean("must_play");
			}
		}
		super.onActivityResult(requestCode, resultCode, intent);
	}

	@Override
	public void onBackPressed() {
		super.onBackPressed();
	}

	@Override
	public void onClick(View view) {
		Station station = getmCurrentStation();
		switch (view.getId()) {
			case R.id.player_play: // play pause
				if (ServiceStreaming.isPlayingRadio()) {
					try {
						stopRadio();
					} catch (Exception e) {
					}
				} else {
					startRadio();
				}
				break;
			case R.id.player_like: // add remove favorite
				mPlayerButtonFavorite.setEnabled(false);
				Station stationLike = getmCurrentStation();
				if (stationLike == null) {
					break;
				}
				if (mPlayerButtonFavorite.isSelected()) {
					try {
						stationLike.isFavorite = 0;
						JsonCacheManager.removeStation(getApplicationContext(), stationLike, JsonCacheManager.FAVORITE_STATION);
						mPlayerButtonFavorite.setSelected(false);
						Utils.customToast(new SpannableStringBuilder(getString(R.string.favorite_station_removed)), getApplicationContext(), false);
					} catch (IOException e1) {
					}
				} else {
					try {
						stationLike.isFavorite = 1;
						JsonCacheManager.addStation(getApplicationContext(), stationLike, JsonCacheManager.FAVORITE_STATION);
						mPlayerButtonFavorite.setSelected(true);
						Utils.customToast(new SpannableStringBuilder(getString(R.string.favorite_station_added)), getApplicationContext(), false);
					} catch (IOException e) {
						Log.e(TAG, "", e);
					}
				}
				Intent intent = new Intent("fav_modification");
				intent.putExtra("isStation", true);
				LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
				mPlayerButtonFavorite.setEnabled(true);
				break;
			case R.id.player_layout: // go to player
				if (!NetworkManager.isConnected(getApplicationContext())) {
					Utils.customToast(new SpannableStringBuilder(getString(R.string.no_network)), getApplicationContext(), false);
					return;
				} else if (!NetworkManager.isConnectedFast(getApplicationContext())) {
					Utils.customToast(new SpannableStringBuilder(getString(R.string.no_fast_network)), getApplicationContext(), false);
					return;
				} else {
					moveToPlayer(getmCurrentStation(), false);
				}
				break;
			case android.R.id.home:
				closeKeyboardFromFocus();
				break;
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
			case R.id.action_facebook:
				confirmDialog(getString(R.string.dialog_confirm_nav), getString(R.string.facebook));
				break;
			case R.id.action_twitter:
				confirmDialog(getString(R.string.dialog_confirm_nav), "https://twitter.com/allzicradio");
				break;
			case R.id.action_google:
				confirmDialog(getString(R.string.dialog_confirm_nav), "https://plus.google.com/115145831019404032385/posts");
				break;
			case R.id.action_option:
				moveToSetting(true);
				break;
		}
		return true;
	}

	/**
	 * setters getters
	 */
	public List<Station> getmListAllZic() {
		return mListAllZic;
	}

	public List<Category> getmListCategory() {
		return mListCategory;
	}

	public void setmListAllZic(List<Station> mListStation) {
		this.mListAllZic = mListStation;
	}

	public void setmListCategory(List<Category> mListCategory) {
		this.mListCategory = mListCategory;
	}

	public static Station getmCurrentStation() {
		if (mCurrentStation != null) {
			return mCurrentStation;
		} else {
			return ServiceStreaming.mStation;
		}
	}

	public static void setmCurrentStation(Station mCurrentStation) {
		BaseActivity.mCurrentStation = mCurrentStation;
	}

	public List<Country> getmListCountry() {
		return mListCountry;
	}

	public void setmListCountry(List<Country> mListCountry) {
		this.mListCountry = mListCountry;
	}

	public List<Department> getmListDepartment() {
		return mListDepartment;
	}

	public void setmListDepartment(List<Department> mListDepartment) {
		this.mListDepartment = mListDepartment;
	}

	/**
	 * Navigation methods
	 */
	public void moveToPlayer(Station station, boolean shouldStartPlay) {
		Intent intent = new Intent(this, ActivityPlayerNew.class);
		intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		intent.putExtra(ActivityPlayerNew.SHOULD_PLAY, shouldStartPlay);
		intent.putExtra(ActivityPlayerNew.STATION, station); // parse the object station
		startActivityForResult(intent, PLAYER_MUST_PLAY_INTENT);
		overridePendingTransition(R.anim.slide_in_right, R.anim.slide_to_behind);
	}

	public void moveToSetting(boolean doAnimation) {
		Intent intent = new Intent(this, ActivitySetting.class);
		intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		startActivity(intent);
		if (doAnimation) {
			overridePendingTransition(R.anim.slide_in_right, R.anim.slide_to_behind);
		}
	}

	public void moveToSearchActivity(String search, boolean doAnimation) {
		Intent intent = new Intent(this, ActivitySearch.class);
		intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		intent.putExtra("search", search);
		startActivity(intent);
		if (doAnimation) {
			overridePendingTransition(R.anim.slide_in_right, R.anim.slide_to_behind);
		}
	}

	/**
	 * Used to prepare the player to play/change station and move to the {@link ActivityPlayer}
	 * 
	 * @param station
	 *        the {@link Station} to be played
	 * @return A boolean equal to <code>true</code> if the player was prepared, else return <code>false</code>
	 */
	public void prepareToPlay(final Station station) {
		if (!NetworkManager.isConnected(getApplicationContext()) || station == null) { // test network
			Utils.customToast(new SpannableStringBuilder(getString(R.string.no_network)), getApplicationContext(), false);
			return;
		}
		// update station play time
		Station currentStation = getmCurrentStation();
		station.setmDate("" + Utils.getCurrentDate());
		setmCurrentStation(station);
		// add to recent
		try {
			if (!JsonCacheManager.isStationSaved(station, getApplicationContext(), JsonCacheManager.RECENT_STATION)) {
				JsonCacheManager.addStation(getApplicationContext(), station, JsonCacheManager.RECENT_STATION);
			} else {
				JsonCacheManager.removeStation(getApplicationContext(), station, JsonCacheManager.RECENT_STATION);
				JsonCacheManager.addStation(getApplicationContext(), station, JsonCacheManager.RECENT_STATION);
			}
		} catch (IOException e) {
		}
		// stop if already playing
		if (currentStation != null && currentStation != station) {
			try {
				stopRadio(); // hum hum so so :/
			} catch (Exception e) {
			}
		}
		// cancel last request
		AdsHttpRequest.getInstance().cancelGetTask();
		moveToPlayer(station, true); // TODO: ˆ changer
		return;
	}

	/**
	 * @param shouldPlay
	 */
	public void startRadio() {
		if (!NetworkManager.isConnected(getApplicationContext())) {
			Utils.customToast(new SpannableStringBuilder(getString(R.string.no_network)), getApplicationContext(), false);
			return;
		} else if (!NetworkManager.isConnectedFast(getApplicationContext())) {
			Utils.customToast(new SpannableStringBuilder(getString(R.string.no_fast_network)), getApplicationContext(), false);
			return;
		}
		// get current radio static instance
		Station station = getmCurrentStation();
		if (station == null) {
			return;
		}
		if (mServiceRadio != null) {
			try {
				if (ServiceStreaming.isRunning()) {
					mServiceRadio.startRadio(station);
				} else {
					final PrefManager preferenceManager = PrefManager.getInstance(getApplicationContext());
					Intent intent = new Intent(BaseActivity.this, ServiceStreaming.class);
					intent.putExtra("station", station);
					intent.putExtra("pub", XMLHandler.MEDIA_FILE);
					intent.putExtra(ActivityPlayerNew.SHOULD_PLAY, true);
					startService(intent);
				}
				mPlayerButtonPlay.setEnabled(false);
				mPlayerButtonPlay.setVisibility(View.INVISIBLE);
				mPlayerLoading.setVisibility(View.VISIBLE);
			} catch (Exception e) {
			}
		}
		// update recent play
		try {
			if (!JsonCacheManager.isStationSaved(station, getApplicationContext(), JsonCacheManager.RECENT_STATION)) {
				JsonCacheManager.addStation(getApplicationContext(), station, JsonCacheManager.RECENT_STATION);
			} else {
				JsonCacheManager.removeStation(getApplicationContext(), station, JsonCacheManager.RECENT_STATION);
				JsonCacheManager.addStation(getApplicationContext(), station, JsonCacheManager.RECENT_STATION);
			}
		} catch (IOException e) {
		}
	}

	/**
	 * Stop the music but not the service. Update the UI
	 * 
	 * @throws Exception
	 *         any Exception
	 */
	public void stopRadio() throws Exception {
		// mServiceRadio.stopStreaming();
		stopService(new Intent(BaseActivity.this, ServiceStreaming.class));
		mPlayerButtonPlay.setEnabled(false);
		mPlayerButtonPlay.setVisibility(View.INVISIBLE);
		mPlayerLoading.setVisibility(View.VISIBLE);
	}

	public void updatePlayerBanner() {
		Station station = getmCurrentStation();
		if (station == null) {
			return;
		}
		ImageManager imageManager = ImageManager.getInstance(getApplicationContext());
		imageManager.setOptions();
		imageManager.setImageLoader();
		try {
			Utils.setImageFromUrl(imageManager, station.getmThumb(), mPlayerThumb);
		} catch (Exception e) {
		}
		if (mServiceRadio != null) {
			if (mServiceRadio.isPlayingRadio()) {
				mPlayerButtonPlay.setImageDrawable(getResources().getDrawable(R.drawable.selector_btn_stop_small));
				mPlayerButtonPlay.setEnabled(true);
				mPlayerButtonPlay.setVisibility(View.VISIBLE);
				mPlayerLoading.setVisibility(View.INVISIBLE);
			} else if (mServiceRadio.isloadingRadio()) {
				mPlayerButtonPlay.setEnabled(false);
				mPlayerButtonPlay.setVisibility(View.INVISIBLE);
				mPlayerLoading.setVisibility(View.VISIBLE);
			} else {
				mPlayerButtonPlay.setImageDrawable(getResources().getDrawable(R.drawable.selector_btn_play_small));
				mPlayerButtonPlay.setEnabled(true);
				mPlayerButtonPlay.setVisibility(View.VISIBLE);
				mPlayerLoading.setVisibility(View.INVISIBLE);
			}
		} // favorite
		if (JsonCacheManager.isStationSaved(station, getApplicationContext(), JsonCacheManager.FAVORITE_STATION)) {
			station.isFavorite = 1;
			mPlayerButtonFavorite.setSelected(true);
		} else {
			station.isFavorite = 0;
			mPlayerButtonFavorite.setSelected(false);
		}
		mPlayerTitle.setText(Html.fromHtml(station.getmTitle()));
		mPlayerSubTitle.setText(Html.fromHtml(station.getmSubtitle()));
	}

	public void showPlayerBanner() {
		mPlayerLayout.setVisibility(View.VISIBLE);
	}

	public void hidePlayerBanner() {
		mPlayerLayout.setVisibility(View.GONE);
		mPlayerLayout.postInvalidate();
	}

	/**
	 * Attach the {@link Service} to the activity so we can get an instance of it.
	 */
	public void bindServices() {
		if (mServiceConnexionRadio != null) {
			bindService(new Intent(BaseActivity.this, ServiceStreaming.class), mServiceConnexionRadio, 0);
		}
	}

	/**
	 * Detach the {@link Service} to the activity
	 */
	public void unbindServices() {
		if (mServiceConnexionRadio != null) {
			unbindService(mServiceConnexionRadio);
		}
	}

	private void confirmDialog(String text, final String url) {
		DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				switch (which) {
					case DialogInterface.BUTTON_POSITIVE:
						Intent intent = new Intent(Intent.ACTION_VIEW);
						intent.setData(Uri.parse(url));
						startActivity(intent);
						break;
					case DialogInterface.BUTTON_NEGATIVE:
						break;
				}
			}
		};
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setMessage(text).setPositiveButton("Oui", dialogClickListener).setNegativeButton("Non", dialogClickListener).show();
	}

	public void closeKeyboardFromFocus() {
		// Close keyboard
		InputMethodManager inputManager = (InputMethodManager) this.getSystemService(Context.INPUT_METHOD_SERVICE);
		// check if no view has focus:
		View v = this.getCurrentFocus();
		if (v == null)
			return;
		inputManager.hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
	}

	public void openKeyboard() {
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
	}

	/**
	 * Download current state
	 */
	protected enum DownloadState {
		/**
		 * Datas are downloading
		 */
		LOADING,
		/**
		 * The download ended
		 */
		LOADED,
		/**
		 * The download failed, it will be restarted
		 */
		RETRY,
		/**
		 * No result return from pull request state
		 */
		NO_RESULT,
		/**
		 * default state
		 */
		DEFAULT
	}

	/**
	 * Update {@link Volley} download state
	 * 
	 * @param mDownloadState
	 *        {@link DownloadState}
	 */
	protected void setmDownloadState(DownloadState mDownloadState) {
		this.mDownloadState = mDownloadState;
	}

	/**
	 * crossfade mLoadingView and mReloadView OR just FadeIn mLoadingView
	 */
	protected void setLoading(View view) {
		Log.i(TAG, "setLoading : " + mDownloadState.toString());
		mReloadView.setVisibility(View.GONE);
		view.setVisibility(View.GONE);
		mNoResultView.setVisibility(View.GONE);
		mLoadingView.setVisibility(View.VISIBLE);
		setmDownloadState(DownloadState.LOADING);
	}

	/**
	 * crossfade any {@link View} and mReloadView
	 * 
	 * @param listener
	 */
	protected void setReload() {
		Log.w(TAG, "setReload : " + mDownloadState.toString());
		mLoadingView.setVisibility(View.GONE);
		mNoResultView.setVisibility(View.GONE);
		mReloadView.setVisibility(View.VISIBLE);
		setmDownloadState(DownloadState.RETRY);
	}

	/**
	 * crossfade the mLoadingView and the {@link View} to display
	 * 
	 * @param view
	 */
	protected void setLoaded(View view) {
		Log.i(TAG, "setLoaded : " + mDownloadState.toString());
		mReloadView.setVisibility(View.GONE);
		mNoResultView.setVisibility(View.GONE);
		mLoadingView.setVisibility(View.GONE);
		view.setVisibility(View.VISIBLE);
		setmDownloadState(DownloadState.LOADED);
	}

	/**
	 * crossfade the mLoadingView and the mNoResultView
	 * 
	 * @param view
	 */
	protected void setNoResult(View view) {
		Log.i(TAG, "setNoResult : " + mDownloadState.toString());
		mReloadView.setVisibility(View.GONE);
		mLoadingView.setVisibility(View.GONE);
		view.setVisibility(View.GONE);
		mNoResultView.setVisibility(View.VISIBLE);
		setmDownloadState(DownloadState.LOADED);
	}
}
